package tech.veedo.munchkin.services.backend.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tech.veedo.munchkin.beans.basic.User;
import tech.veedo.munchkin.beans.backend.Mapping;
import tech.veedo.munchkin.constants.UpgradeTactic;
import tech.veedo.munchkin.mappers.backend.MappingMapper;
import tech.veedo.munchkin.services.backend.MappingService;
import tech.veedo.ragdoll.exception.GlobalException;

import java.util.HashMap;
import java.util.Objects;

@Slf4j
@Service
public class MappingServiceImpl extends ServiceImpl<MappingMapper, Mapping> implements MappingService {

    @Override
    @Transactional
    public boolean saveMapping(Mapping mapping, User user) {
        if (mapping.isHook()) {
            Mapping beHooked = getById(mapping.getHookMappingID());
            if (ObjectUtils.isEmpty(beHooked)) {
                throw new NullPointerException("要挂接实体工作流在数据库中未找到, 请重新获取列表");
            }
        }
        Mapping forInsert = new Mapping()
                .setVersion(1L)
                .setName(mapping.getName())
                .setWorkflowID(mapping.getWorkflowID())
                .setOrgCode(mapping.getOrgCode())
                .setOrgName(mapping.getOrgName())
                .setPublik(mapping.isPublik())
                .setInUsing(false)
                .setHook(mapping.isHook())
                .setHookMappingID(mapping.isHook()?mapping.getHookMappingID():null)
                .setTactic(ObjectUtils.isNotEmpty(mapping.getTactic())?mapping.getTactic(): UpgradeTactic.STOP_IF_USE);

        return save(forInsert);
    }

    @Override
    @Transactional
    public boolean updateMapping(Mapping mapping, User user) {
        Mapping fromDB = getById(mapping.getId());
        if (ObjectUtils.isEmpty(fromDB)) {
            throw new NullPointerException("实体工作流(id:"+mapping.getId()+")在数据库中未找到，请刷新");
        }
        if (!Objects.equals(fromDB.getVersion(), mapping.getVersion())) {
            throw new IllegalStateException("当前实体工作流版本与操作时不符，请刷新");
        }

        Mapping forUpdate = new Mapping();
        forUpdate.setId(mapping.getId());
        forUpdate.setName(mapping.getName())
                .setPublik(mapping.isPublik())
                .setHook(mapping.isHook())
                .setHookMappingID(mapping.isHook()?mapping.getHookMappingID():null)
                .setTactic(ObjectUtils.isNotEmpty(mapping.getTactic())?mapping.getTactic(): UpgradeTactic.STOP_IF_USE);

        return updateById(forUpdate);
    }

    @Override
    public Page<Mapping> pageMapping(HashMap<String, Object> params) {
        Page<Mapping> page = new Page<>();
        if (params.containsKey("current")) {
            try {
                page.setCurrent(Long.parseLong(String.valueOf(params.get("current"))));
            } catch (Exception e) {
                e.printStackTrace();
                page.setCurrent(1L);
            }
        }
        if (params.containsKey("size")) {
            try {
                page.setSize(Long.parseLong(String.valueOf(params.get("size"))));
            } catch (Exception e) {
                e.printStackTrace();
                page.setSize(20L);
            }
        }
        QueryWrapper<Mapping> wrapper = new QueryWrapper<>();
        wrapper.eq("workflow_id", Long.parseLong(String.valueOf(params.get("workflowID"))))
                .eq("org_code", String.valueOf(params.get("orgCode")));
        return page(page, wrapper);
    }

    @Override
    @Transactional
    public boolean deleteMapping(Long id) {
        Mapping fromDB = getById(id);
        if (ObjectUtils.isEmpty(fromDB)) {
            throw new NullPointerException("实体工作流(id:"+id+")在数据库中未找到，请刷新");
        }
        if (fromDB.isInUsing()) {
            throw new IllegalStateException("实体工作流正在应用中，请停用后删除");
        }
        return removeById(id);
    }

    @Override
    @Transactional
    public boolean start(Long id) {
        Mapping fromDB = getById(id);
        if (ObjectUtils.isEmpty(fromDB)) {
            throw new NullPointerException("实体工作流(id:"+id+")在数据库中未找到，请刷新");
        }

        QueryWrapper<Mapping> wrapper = new QueryWrapper<>();
        wrapper.eq("workflow_id", fromDB.getWorkflowID())
                .eq("org_code", fromDB.getOrgCode())
                .eq("in_using", true);
        Mapping inUsing = getOne(wrapper);
        if (ObjectUtils.isNotEmpty(inUsing)) {
            throw new GlobalException("已经有正在使用的实体工作流了，请停用后再启用");
        }

        Mapping forStart = new Mapping();
        forStart.setId(id);
        forStart.setInUsing(true);

        return updateById(forStart);
    }

    @Override
    @Transactional
    public boolean stop(Long id) {
        Mapping fromDB = getById(id);
        if (ObjectUtils.isEmpty(fromDB)) {
            throw new NullPointerException("实体工作流(id:"+id+")在数据库中未找到，请刷新");
        }

        // 有审批中的不能停
        // code here...

        Mapping forStop = new Mapping();
        forStop.setId(id);
        forStop.setInUsing(false);

        return updateById(forStop);
    }

}